home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-09-15 | 231.9 KB | 384 lines | [ONLN/HLX2] |
- Apple Remote AccessAdd-on Security InterfaceAuthor: Farzad SarabiVersion 1.0November 4, 1993Copyright © 1992, 1993 Apple Computer, Inc.Table of ContentsIntroduction 1Overview 2Security Module Structure 5Module Information Resource ('sinf' ID 200) 6Code Resource Structure 8User Configuration (UCNF Resource ID 200) 11Client-side Protocol (CLPR Resource ID 200) 12Server-side Protocol (SRPR Resource ID 200) 13Connection Configuration (CCNF Resource ID 200) 14Client Side Line-level (CLLN Resource ID 200) 15Actions 16kSecurityStartup 16kSecurityShutdown 16kSecurityBegin 16kSecurityEnd 16kSecurityDataAvailable 16kSecurityAbort 16kSecurityTickleAction 17ARA Service Routines 18ARARead 19ARAWrite 21ARALogMessage 22ARACallBackAt 23ARAAllowUser 24ARADontAllowUser 25ARAReadSecurityData 26ARAReadLockSecurityData 27ARAWriteSecurityData 28ARAUnlockSecurityData 29ARAGetUserInfo 30ARATickleMe 31ARACompleteOperation 32Appendix A: Security Interface Header File 33Appendix B: Security Module Shell 41Appendix C: Miscellaneous 48Runtime Environment 48Building an Add-on Security Module 48ARA Security Interface Disk 49IntroductionThis document describes the add-on security interface used in Apple Remote Access (ARA). This document is written for a security module writer, and explains the ARA interface as seen from an add-on security module.Add-on security modules (security modules) contain code resources that allow additional methods of authenticating users. ARA uses passwords and a call-back mechanism as its default security. If you have a system for identifying a user, you can develop a security module to integrate your authentication methods into ARA.We have defined two types of security devices. Devices that sit in front of or behind a modem and physically prevent a connection prior to user authentication are called line-level security devices. Systems that perform their authentication after the ARA server and its client have established a connection are classified as protocol-level security devices. You can develop security modules for each type of device.The next section gives a brief overview of add-on security modules.The Security Module Structure section describes a module and its structure in more detail.The Code Resources section describes the different kinds of code resources that can exist in a security module.The Actions section describes the actions ARA sends to code resources to request services.The ARA Service Routines section describes the services that ARA provides to security modules.Appendix A is the header file for gaining access to ARA Service Routines.Appendix B is an empty shell for building a code resource.Appendix C contains miscellaneous information about security module's such as a modules runtime environment, how you can build a module, and the enclosed developer disk contents.OverviewA security module is a Macintosh file type 'CLMP'. The creator is vendor specific. You can request a creator for your security module from Apple Developer Technical Support (DTS).Internally a security module contains a number of special resources. Every module must contain an information resource that describes your modules capabilities. Additionally your module may contain a number of code resources. These code resources are executed to perform various functions (e.g. authentication, configuration) for your security module. ARA then can use your module to authenticate a user's identity beyond the password mechanism that it contains. ARA security modules that are placed in the Extensions folder.The following diagram illustrates the contents of a security module:The information resource is described in the module Information Resource section.Each of the code resources provides an entry point. This is a routine which will be called when ARA needs to execute a code resource. The entry point routine and the operations it must support are described in the Code Resource Structure section.When a code resource is loaded, it will be able to access ARA to request certain services. For example it can have data sent to the remote machine. These services are provided as routines that can be called from a security module. They are described in the ARA Service Routines section.The following diagram is a high level view of a loaded code resource:Security Module StructureA security module is built by creating a Macintosh file that has a 'CLMP' type. This is used by ARA to identify the file as a security module. The module has to be placed in the Extensions folder for ARA to find it. You can do this by dragging it on top of your system folder after installing ARA. The module's creator is defined by you. You must request a creator from Developer Technical Support (DTS).Additionally the file must contain at least a 'sinf' resource, and a number of code resources for performing various operations. The 'sinf' resource and the code resources are described below.Currently there are five types of code resources that ARA supports. They are described in sub-sections below. Code resources must have the appropriate type, and their resource ID should be 200.Module Information Resource ('sinf' ID 200)Your module must have a 'sinf' resource with a resource ID of 200. The 'sinf' resource describes what the module's capabilities are.In your resource definition file, you should create a 'sinf' resource, and fill in the appropriate fields. The template for the resource is defined in a file named "SecurityTypes.r". This file is found on the developer disk. The following is the template for a 'sinf' resource:type 'sinf' { /* security information resource */ unsigned longint; /* fflags contains info about module */ literal longint; /* fsignature identifies module */ unsigned longint; /* fversion */ unsigned longint; /* fmin_version */ unsigned longint; /* fmax_version */ unsigned longint; /* fserver_data */ unsigned longint; /* fclient_data */ pstring[ 31 ]; /* module name */};The first longint is a set of flags that define what the capabilities of the module are. The values for the flags are defined in "SecurityResInfo.h", found on the developer disk. The values should be a combination of the following using the "OR" operator:kSecurityHasLineLevel Use this flag if your module is to be used for line-level authentication of a user. This flag causes the module to be displayed on the client side. It let's the user select this module for a connection document, used to connect to a port with a physical security device. kSecurityHasProtocolLevel This flag indicates the module provides protocol level authentication. It can be used in combination with the kSecurityHasServerSide and kSecurityHasClientSide flags to indicate if the module supports the client side, server side, or both. kSecurityHasServerSide This flag is set for a module that provides the code resources needed for the server side. Any module that has code to be executed on the server should set this flag, including user configuration. kSecurityHasClientSide This flag is set for a module that provides code resources needed for the client side. Any module that has code to be executed on the client should set this flag. kSecurityHasUserConfig This flag is used for a protocol-level module that has a code resource for configuring users on the server. Has 'UCNF' resource. kSecurityHasConnectionConfig This flag is used for a line-level module that has a code resource for security configuration on the client side. Has a 'CCNF' resource. kSecurityHasUserDialog Don't use this flag. kSecurityHasConnectionDialog Don't use this flag. The second longint is the signature of the module. This value uniquely identifies your security module. You should reserve a value through Apple Developer Technical Support (DTS). This value should be the same as your file's creator, but it can be different. When they are different, ARA uses the value defined in the 'sinf' resource. For protocol-level modules this signature is used to associate a client module with the server module.The next three longints are version numbers and are only used for protocol level modules. The first field is "fversion" and defines the module's version. The field after "fversion" are "fmin_version", and "fmax_version". For protocol-level authentication, they are used for checking the client module's compatibility with the server's. The client's "fversion" must be a number between the server module's "fmin_version" and "fmax_version". The next two longints, "fserver_data" and "fclient_data", are not used, and should be set to zero.The last field is a Pascal string that is your module's name. This name is used in dialog boxes and anywhere your modul'es name is displayed.Code Resource StructureThe following sub-sections describe the structure of code resources.MySecurityProcEntryEvery code resource must provide a routine named "MySecurityProcEntry". This is the entry point to the code resource. ARA calls it through the Security Interface. It should be defined as follows:pascal long MySecurityProcEntry( SecurityActions Action, SecurityReference MyReference, long LongParam )ARA sends actions to your code resources to request it to perform a service. You should process the actions and return control to ARA as quickly as possible. Actions are defined in the file SecurityPublic.h. The "Actions" section describes actions in detail. The following is a list of the actions:kSecurityStartupkSecurityShutdownkSecurityBeginkSecurityEndkSecurityDataAvailable,kSecurityAbortkSecurityTickleActionMyReference is a unique value that defines an instance of the code resource. It is used when you call any of the ARA Service Routines. It uniquely identifies your thread.LongParam is used to pass additional information for an action. Currently it is only used with kSecurityTickleAction.Your entry routine should process the action as soon as possible. It should not stay go into any loops. It can post asynchronous calls to ARA and other Toolbox routines, but it should return control back to ARA quickly. YOU MUST RETURN CONTROL BACK TO ARA AS SOON AS POSSIBLE.Your routine's return value is a result code ARA examines for possible errors in "MySecurityProcEntry". The possible result codes are "SecurityErrors" defined in "SecurityPublic.h". Return "kSecurityNoErr" if your routine is successful.SecurityInterface.o"SecurityInterface.o" is the glue file that provides the ARA Service Routines. It must be linked with each code resource. When linking a code resource, you must have "SecurityInterface.o" as the first file in the linker's object file list. The MPW linker does not shuffle code. The entry point to "SecurityInterface.o" must become the entry point to your code resource.MPW linker uses the -m option to perform code-flow analysis and remove any dead code. To keep your executable code from being stripped, you must provide the following option in the linker command line:-m SECURITYINTERFACEENTRYPROCCompletion RoutineMost of the ARA Service Routines are asynchronous. After an asynch ARA routine finishes, it informs you code resource by calling a completion routine. Your completion routine should have the following declaration:pascal void MyCompletionProc( SecurityReference MyReference, int ResultCode, void * DataPtr, int DataSize, long CompletionParam )You pass a pointer to your completion routine as one of the parameters to asynchronous ARA Service Routines.MyReference should is the same value passed to "MySecurityProcEntry". It identifies your instance.ResultCode is the result of the asynchronous ARA Service you had requested. It will be non zero if the operation failed. It will contain one of the values in ARAErr defined in SecurityPublic.h. You should check its value at the start of your completion routine before you do any other processing. If a read or write times out, the ResultCode will be ARATimeout.DataPtr is the pointer you passed to the asynch ARA Service Routine. E.g. this will point to the data read by ARARead.DataSize will be the actual size of processed data. E.g. the number of bytes read by ARARead.CompletionParam is an additional long you provide. Its value will be the same value you passed to the asynch ARA Service Routine. You can use it as a state indicator. E.g. you can define an enumeration containing the set of all your states. When you call an asynch ARA routine, pass the state you want to be in when the call is done. E.g. pass "kFinished1stRead" to ARARead. When your completion routine gets called with CompletionParam equal to "kFinished1stRead", the ARARead has finished and you can go to the next state. See the sample module on the developer disk for an example of this.You should not call any Memory Manager routines, or any routines that result in a Memory Manager call from a completion routine. If you need to call these types of routines, call ARATickleMe and handle it in the kSecurityTickleAction.Runtime Environment (A5 World)An A5 World is setup for your code resource by ARA. You don't need to be concerned with initializing or setting up the A5 world in the code resource. ARA sets up the A5 world prior to executing any of the code resource (entry routine, and completion routines). Since the code resource has an A5 world, it you can have static (global) data and use the data the same way as an application.During the execution of your code resource, the resource fork of the security module is open, and it is put on top of the resource forks stack. The file is opened in read only mode, so you should not attempt to write any data to the module's resource fork. A better way of storing data is to store it in a separate preference file, which will not be deleted when you update a user's security module.You can make calls to Mac Toolbox routines. Whenever possible you should call asynchronous routines, so you can return control to ARA. Furthermore, you should not go into any loops or call SystemTask as a way of returning control to ARA.ARA Service RoutinesARA provides a number of services accessible through ARA Service Routines. The header file "SecurityInterface.h" has the declarations for these routines. To use them you must link with "SecurityInterface.o".The ARA Service Routines are described in detail in a later section.User Configuration (UCNF Resource ID 200)This code resource is executed when a user window is open on the ARA server admin, and the security module's configuration button is selected. It is used for configuring protocol-level security information on a per-user basis. The code resource should display a modal dialog box and get any needed information. It can store 150 bytes of data for each user (see ARAWriteSecurityData, and ARAReadSecurityData).On kSecurityBegin you should start your processing, e.g. request to read the existing security data (ARAReadLockSecurityData), or to get the user's name (ARAGetUserInfo). When you've obtained this information, you can call ARATickleMe to put up the modal dialog box (it must be a modal dialog box). You must display the user's name at the top of this dialog box. The user can then input/modify the information and either save or cancel. If the user selects to save the data, you must write it out by calling ARAWriteSecurityData. This information will then be available to the server-side protocol-level authentication module.The following ARA Service Routines can be used by a UCNF code resource:ARALogMessageARAReadSecurityDataARAReadLockSecurityDataARAUnlockSecurityDataARAWriteSecurityDataARAGetUserInfoARATickleMeARACompleteOperationClient-side Protocol (CLPR Resource ID 200)This code resource is executed on the ARA client for protocol-level authentication. The corresponding server-side protocol-level module is also executed on the server, and the two module's can communicate with each other.The client module's state should be driven by the server, and when the authentication has been completed, both sides should call ARAAllowUser/ARADontAllowUser, so ARA can progress to the next state.A CLPR module can pass a maximum of 500 bytes of data to ARAWrite/ARARead. The ARAWrite and ARARead will communicate with the server-side protocol (i.e. ARARead on the client side will read data written by the server module).On kSecurityBegin you should start your state machine, getting information from the user and sending it to the server module. The server module should inform the client module when the user is authenticated or rejected, at which time it should call ARAAllowUser, or ARADontAllowUser.The following ARA Service Routines can be used by a CLPR code resource:ARAReadARAWriteARALogMessageARAAllowUserARADontAllowUserARATickleMeARACompleteOperationServer-side Protocol (SRPR Resource ID 200)This code resource is executed on the server to authenticate a user after the ARA protocol has been established. It can communicated with the corresponding client authentication module. ARA loads the client module automatically.This code resource should get the user information from the client module and determine if the user should be allowed in. Once a user has been authenticated or rejected, this code resource should inform the client side, and then call ARAAllowUser/ARADontAllowUser. The client code resource should also call ARAAllowUser/ARADontAllowUser.A SRPR code resource can write and read a maximum of 500 bytes of data using ARAWrite or ARARead. The data is exchanged with client module.This code resource can use ARAReadLockSecurityData, ARAReadSecurityData, ARAWriteSecurityData, and ARAUnlockSecurityData to access and modify the 150 bytes of security data associated with each user. Each security module can have 150 bytes of data for each user.The following ARA Service Routines can be used by a SRPR code resource:ARAReadARAWriteARALogMessageARACallBackAtARAAllowUserARADontAllowUserARAReadSecurityDataARAReadLockSecurityDataARAUnlockSecurityDataARAWriteSecurityDataARAGetUserInfoARAGetMySessionRefARATickleMeARACompleteOperationConnection Configuration (CCNF Resource ID 200)A Connection Configuration code resource is executed on the client side when the user selects "Configuration" button on the client in a connection document's security option. It can store 150 bytes of data in a connection document for a line-level security device.It should display a modal dialog and get any information relevant to connections with line-level security. You can use ARAReadLockSecurityData, ARAReadSecurityData, ARAWriteSecurityData, and ARAUnlockSecurityData to access and modify the security data.On kSecurityBegin you should get the existing security data. Once you have obtained the data, you should display a dialog box, and allow the user to modify it. When the user is done, you can write the security data if it was modified, using ARAWriteSecurityData.The following ARA Service Routines can be used by a CCNF code resource:ARAReadSecurityDataARAReadLockSecurityDataARAUnlockSecurityDataARAWriteSecurityDataARATickleMeARACompleteOperationClient Side Line-level (CLLN Resource ID 200)A client-side line-level code resource is executed after a physical connection has been established, using a connection document configured with security. It should communicate with the line-level device, prompting the user for any information the device requires.A CLLN code resource can use the ARARead and ARAWrite to communicate with the line-level device on the server. The data being read or written is sent over the physical line without any packetization. Your code resource gets control of the line after a connection is established, but before your authentication device allows connection to the ARA server.On kSecurityBegin you should start the communication process with the server line-level device. You can display a dialog box to obtain information from the user. Once the physical device has authenticated or rejected the user the code resource should call ARAAllowUser or ARADontAllowUser to let ARA transition to the next state.You can use ARAReadSecurityData to access the 150 bytes of data stored in the connection document. You can not modify this information during authentication. The security data is stored in an alias to a remote server as well as the original connection document, so you can get the data even if the connection is initiated from an alias to a remote server.A CLLN code resource can use the following ARA Service Routines:ARAReadARAWriteARAAllowUserARADontAllowUserARAReadSecurityDataARATickleMeARACompleteOperationActionsActions are one of the parameters passed to your code resource's entry routine. ARA sends them to request a service from your code resource. All actions are sent during main thread time, so you can allocate memory and make calls to Mac Toolbox routines. The code resource's A5 world is setup prior to calling your routine. The resource fork of your module is open and on top of the resources stack.You should process actions as quickly as possible. You should not go into loops and use SystemTask calls as a way of returning control back to ARA.kSecurityStartupkSecurityStartup is sent immediately after your code resource is loaded. You can allocate any needed memory during the processing of this action, but you should not make any calls to any of the ARA Service Routines. Once processed, you should return kSecurityNoErr. Generally you should use kSecurityBegin to start any processing.kSecurityShutdownkSecurityShutdown is the last action sent prior to unloading your code resource. The code resource will not be called any more after this action. You can release any allocated memory. Make sure you have cleaned everything up before returning. You can not use any of the ARA Service Routines during kSecurityShutdown.kSecurityBeginkSecurityBegin is sent to request your code resource to perform its operation. E.g. requesting a protocol-level module to authenticate a user. The code resource should start the operation that it is responsible for. You can allocate memory and other needed resources. You can also call ARA Service Routines asynchronously.kSecurityEndkSecurityEnd is sent when the operations that the resource performs are being finished. You should do your cleanup at this time. You can not make any calls to ARA Service Routines after or during this action.kSecurityDataAvailablekSecurityDataAvailable is not being used in this release.kSecurityAbortkSecurityAbort is sent when the operation of your code resource is being aborted. You should stop any further processing by your code resource (including in your completion routine. E.g. through the use of a flag). Your code resource should terminate any outstanding asynch calls to routines other than ARA Service Routines. Outstanding ARA Service Routines will be aborted by ARA.kSecurityTickleActionkSecurityTickleAction is sent to your code resource periodically. You can also request a kSecurityTickleAction explicitly by calling the ARATicleMe routine. When you call ARATickleMe you pass an additional parameter which is sent to your "MySecurityProcEntry" as the LongParam. This additional parameter can be used as a state indicator. E.g. an asynchronous call has finished, so from your completion routine you call ARATickleMe with the state indicator "DidMyAsynchCall" (this can be a value in an enum). In processing of kSecurityTickleAction you check the LongParam to see if it matches "DidMyAsynchCall". If it matches you know you have finished your asynchronous operation and are ready to transition to the next state. You should also do an ARATickleMe when you need to perform main thread time operations (e.g. allocate memory) . When kSecurityTickleAction is being sent periodically by ARA LongParam will be 0. For an example on the use of kSecurityTickleAction and ARATickleMe refer to the Sample module.ARA Service RoutinesARA Service Routines are a set of functions that code resources have access to. Using these routines, code resources can request ARA services. The following is a list of ARA Service Routines:ARAReadARAWriteARALogMessageARACallBackAtARAAllowUserARADontAllowUserARAReadSecurityDataARAReadLockSecurityDataARAWriteSecurityDataARAUnlockSecurityDataARAGetUserInfoARATickleMeARACompleteOperationThe following sub-sections describe each of the routines. NoteAll of the routines expect a MyReference parameter. This value is passed to "MySecurityProcEntry", and is a unique value representing the instance of the security code resource.ARAReadSyntaxpascal ARAErr ARARead( SecurityReference MyReference, void * DataPtr, int DataSize, SecurityCompletionProc CompletionProc, long CompletionParam );DescriptionThis routine is used to issue an asynchronous read call to ARA. The read will complete either when ARA times out, or the number of bytes requested is read. This read is used to read data coming from the remote machine. The protocol-level modules read from each other. The line-level module reads from a device on the server side.ParametersMyReference is the unique identifier passed to the code resource's entry routine.DataPtr points to a location where the data will be read to. It must not be released while the asynchronous read has not completed.DataSize is the maximum number of bytes to be read to DataPtr. The maximum data size is 500 bytes.CompletionProc is a function pointer you provide to be called when the read operation has been completed. If a time-out occurs the CompletionProc is called with a kARATimeout result code.CompletionParam is additional information you can provide which will be passed to the CompletionProc.Return ValueResult code. Non kARANoErr result codes are usually because the call was not queued.NoteThis is an asynchronous call and can be called during interrupt time. The DataPtr field must not be released until the call has completed.See AlsoARAWriteARAWriteSyntaxpascal ARAErr ARAWrite( SecurityReference MyReference, void * DataPtr, int DataSize, SecurityCompletionProc CompletionProc, long CompletionParam );DescriptionThis routine can be used to write data to the remote machine. For protocol-level authentication the data is transferred over a reliable link, whereas for line-level authentication the data is just transferred over the connection without any packetization. Protocol-level modules write to each other. Line-level modules write to a security device on the server side.ParametersMyReference is the unique reference passed to the code resource's entry routine.DataPtr is a pointer to the data to be written out.DataSize is the number of bytes to be written. A maximum of 500 bytes can be written.CompletionProc is a pointer to a completion routine which will be called when the write has been completed.CompletionParam is additional information you can provide which will be passed to the CompletionProc.Return ValueResult code. Errors are usually caused when the write call can not be queued.NoteThis is an asynchronous call and can be called at interrupt time. The DataPtr field must not be released until the call has been completed.See AlsoARAReadARALogMessageSyntaxextern pascal ARAErr ARALogMessage( SecurityReference MyReference, char * Message, SecurityCompletionProc CompletionProc, long CompletionParam );DescriptionYou can use this routine to have a message logged to the ARA log file.ParametersMessage is a Pascal string which will be stored in the log file.Return ValueResult code.NoteThis is an asynchronous call that can be made during interrupt time.ARACallBackAtSyntaxpascal ARAErr ARACallBackAt( SecurityReference MyReference, char * DialString, SecurityCompletionProc CompletionProc, long CompletionParam );DescriptionThis routine can be used to change the phone number which ARA will call back at. In order for this routine to work the call-back must be enabled for the given user. The call-back won't be executed until all other add-on security modules have been executed.The new number is only used for the current session, and won't change the permanent call-back number.ParametersDialString is a Pascal string which contains the phone number to dial. It must be a valid phone number.CompletionProc is a routine pointer which will be called when the phone number has been assigned (not when the call-back has been made).CompletionParam can contain additional information you can supply to be passed on to the CompletionProc.Return ValueResult code.NoteThis is an asynchronous call that can be made at interrupt time.The CompletionProc is called when the DialString has been stored by ARA. Since another security module could override this DialString by another call to this routine, the user may not get called at this DialString.This routine can only be used by a server-side protocol-level code resource (SRPR)ARAAllowUserSyntaxpascal ARAErr ARAAllowUser( SecurityReference MyReference, SecurityCompletionProc CompletionProc, long CompletionParam );DescriptionThis routine is used to let ARA know that the user has been authenticated. It also informs ARA that the operation has been completed. ARA will then send the code resource's entry routine a kSecurityEnd action, after which ARA proceeds to the next state.ParametersCompletionProc is a completion routine which will be called when ARA has accepted this call.CompletionParam is additional information you can supply that will be provided to the CompletionProc.Return ValueResult code.NoteThis is an asynchronous call that can be made during interrupt time.See AlsoARADontAllowUser, ARACompleteOperationARADontAllowUserSyntaxpascal ARAErr ARADontAllowUser( SecurityReference MyReference, char * Message, SecurityCompletionProc CompletionProc, long CompletionParam );DescriptionYou can call this routine when the user has failed authentication. ARA will send a kSecurityEnd action to the code resources entry routine, after which ARA will tear down the connection.ParametersMessage is an optional Pascal string which states why the user failed authentication. You can pass a NIL for the pointer.CompletionProc is your routine which will be called when ARA has accepted this call.CompletionParam is a parameter you can supply which is passed to the CompletionProc.Return ValueResult code.NoteThis is an asynchronous call that can be made during interrupt time.See AlsoARAAllowUser, ARACompleteOperationARAReadSecurityDataSyntaxpascal ARAErr ARAReadSecurityData( SecurityReference MyReference, void * DataPtr, int DataSize, SecurityCompletionProc CompletionProc, long CompletionParam );DescriptionThis routine is used to read data for the given type of security module which is associated with either a user or a connection. On the server this data is associated with a given user. On the client side this data is associated with the connection. The maximum amount of data that can be stored is 150 bytes.ParametersDataPtr points to where the security data is to be read to.DataSize is the maximum amount of data to read. It should not be larger than 150.CompletionProc is a pointer to a routine which will be called when the data has been read.CompletionParam is additional information you can provide to be passed to the CompletionProcReturn ValueResult code.NoteOn the ARA server this data is associated with a given user and stored in the users and groups database. On the client side this data is associated with a given connection.See AlsoARAReadLockSecurityData, ARAWriteSecurityData, ARAUnlockSecurityDataARAReadLockSecurityDataSyntaxpascal ARAErr ARAReadLockSecurityData( SecurityReference MyReference, void * DataPtr, int DataSize, SecurityCompletionProc CompletionProc, long CompletionParam );DescriptionThis routine is used to read and lock data for the given type of security module which is associated with either a user or a connection. On the server this data is associated with a given user. On the client side this data is associated with the connection. The maximum amount of data that can be read or written is 150 bytes. You should use the ARAReadLockSecurityData instead of ARAReadSecurityData if you plan to modify or write the security data. This is crucial on the server, because you can have multiple threads attempting to modify the same data.ParametersDataPtr points to where the security data is to be read to.DataSize is the maximum amount of data to read. It should not be larger than 150.CompletionProc is a pointer to a routine which will be called when the data has been read.CompletionParam is additional information you can provide to be passed to the CompletionProcReturn ValueResult code.NoteOn the ARA server this data is associated with a given user and stored in the users and groups database. On the client side this data is associated with a given connection.You must call ARAUnlockSecurityData to remove the lock from the security data.See AlsoARAReadSecurityData, ARAWriteSecurityData, ARAUnlockSecurityDataARAWriteSecurityDataSyntaxpascal ARAErr ARAWriteSecurityData( SecurityReference MyReference, void * DataPtr, int DataSize, SecurityCompletionProc CompletionProc, long CompletionParam );DescriptionThis routine can be used by the security modules (mostly configuration code resources) to store configuration data which is associated with either a user or a connection. On the server this data is associated with a user. On the client this data is associated with a connection.ParametersDataPtr points to the data to be stored.DataSize is the number of bytes to store. It should be less than or equal to 150.CompletionProc is a pointer to a completion routine that will be called when the data has been written.CompletionParam is additional information you can provide to be passed to the CompletionProc.Return ValueResult code.NoteOn the ARA server this data is associated with a given user and stored in the users and groups database. On the client side this data is associated with a given connection.A line-level authentication code resource (CLLN) can not modify the security data.See AlsoARAReadSecurityData, ARAReadLockSecurityData, , ARAUnlockSecurityDataARAUnlockSecurityDataSyntaxpascal ARAErr ARAUnlockSecurityData( SecurityReference MyReference, SecurityCompletionProc CompletionProc, long CompletionParam );DescriptionThis routine removes a lock from security data that has been locked using ARAReadLockSecurityData.ParametersCompletionProc is a pointer to a completion routine that will be called when the data has been written.CompletionParam is additional information you can provide to be passed to the CompletionProc.Return ValueResult code.NoteYou must call ARAUnlockSecurityData after you have called ARAReadLockSecurityData.See AlsoARAReadSecurityData, ARAReadLockSecurityData, ARAWriteSecurityDataARAGetUserInfoSyntaxpascal ARAErr ARAGetUserInfo( SecurityReference MyReference, void * DataPtr, int DataSize, SecurityCompletionProc CompletionProc, long CompletionParam );DescriptionThis routine is used to get information about the user. Currently it returns the user's name. On the server this is the information for the user dialing in, or being configured.ParametersDataPtr points to where this information will be stored.DataSize is the maximum number of bytes to be read.CompletionProc is a completion routine that will be called when the information has been read.CompletionParam is additional information you can provide to be passed to the CompletionProc.Return ValueResult code.ARATickleMeSyntaxpascal ARAErr ARATickleMe( SecurityReference MyReference, long TickleParam );DescriptionThis routine causes ARA to send a kSecurityTickleAction to the code resource's entry routine. For example, you can use this routine from completion routines to have your entry routine invoked.ParametersTickleParam is additional information you can provide which will be passed to the entry routine in its LongParam parameter. When ARA calls the entry routine with a kSecurityTickleAction it passes a 0 for the LongParam parameter. You can use this as a state indicator.Return ValueResult code.NoteThis function can be called during interrupt time. The kSecurityTickleAction is sent to the "MySecurityProcEntry" at SystemTask time.See AlsokSecurityTickleActionARACompleteOperationSyntaxpascal ARAErr ARACompleteOperation( SecurityReference MyReference );DescriptionYou call this routine when you need to end the operation the code resource is performing. It causes ARA to send a kSecurityEnd action. For example the configuration code resource should call this routine when the user has finished inputting information into its dialog box.ParametersMyReference is the unique reference passed to the code resource's entry routine.Return ValueResult code.See AlsokSecurityBegin, and kSecurityEnd actionsAppendix A: Security Interface Header File//234567890123456789012345678901234567890123456789012345678901234567890123456789//===========================================================================// File: SecurityInterface.h//// This file is the header file which a third party security vendor can// use to create an add-on security module. The add-on security modules// can be used to integrate a security device with Apple Remote Access.//// Copyright © 1992, 1993 Apple Computer Inc.// All rights reserved//// Author: Farzad Sarabi//// Modification history://// 9/29/1993 Farzad Removed declarations for some routines that were// obsolete.// 2/15/1993 Farzad The A5 world and a working environment is now// setup for the security modules. As a result of// this some of the routines in this module are// obsolete. Among these are ARAGet/SetMyPrivateData,// ARAGetMyResFile.// 10/6/1992 Farzad Created//===========================================================================#ifndef SECURITY_INTERFACE#define SECURITY_INTERFACE 1#ifndef __FILES__#include <Files.h>#endif#ifndef SECURITY_PUBLIC#include "SecurityPublic.h"#endif//===========================================================================// Macros//===========================================================================#define kSecurityInterfaceVersion 0x0100 // 0x0100 will be release 1#ifdef __cplusplusextern "C" { // in case we are linking into C++ code#endif//===========================================================================// Types//===========================================================================// actions are defined in the SecurityPublic.h file// ARAErr is defined in SecurityPublic.h// SecurityEntryProc is defined in SecurityPublic.h// SecurityCompletionProc is defined in SecurityPublic.h//===========================================================================// Data//===========================================================================//===========================================================================// Functions//===========================================================================// the following are functions you can call to have AppleTalk Remote Access// perform these servicesextern pascal ARAErr ARARead( SecurityReference MyReference, void * DataPtr, int DataSize, SecurityCompletionProc CompletionProc, long CompletionParam );//===========================================================================// Description: this routine is used to post an asynchronous read// operation for data coming from the remote machine.// This routine can be used by line-level and protocol-level// authentication modules. It is not available for // configuration modules.//// Parameters: MyReference this module's unique reference// DataPtr where to put the read data// DataSize the maximum number of bytes to read// CompletionProc this routine will be called when the// read request has finished// CompletionParam this is information you can provide to// be passed to the completion proc//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/6/1992//// Modifications:////===========================================================================extern pascal ARAErr ARAWrite( SecurityReference MyReference, void * DataPtr, int DataSize, SecurityCompletionProc CompletionProc, long CompletionParam );//===========================================================================// Description: this routine is used to asynchronously write data to// the remote machine. It can be used by line-level and// protocol-level authentication modules.//// Parameters: MyReference your unique reference// DataPtr the data to be written out// DataSize the amount of data to write// CompletionProc this routine is called when the data// has been written out// CompletionParam this is extra information you can provide// to be passed to the CompletionProc//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/6/1992//// Modifications:////===========================================================================extern pascal ARAErr ARALogMessage( SecurityReference MyReference, char * Message, SecurityCompletionProc CompletionProc, long CompletionParam );//===========================================================================// Description: you can use this routine to put a message in AppleTalk// remote accesses log file.//// Parameters: MyReference your unique reference// Message a Pascal string which will be logged to// in the log file// CompletionProc this routine will be called when the// log message has been completed.// CompletionParam additional information you can supply to// be passed on to the completion proc//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/6/1992//// Modifications:////===========================================================================extern pascal ARAErr ARACallBackAt( SecurityReference MyReference, char * DialString, SecurityCompletionProc CompletionProc, long CompletionParam );//===========================================================================// Description: this routine can be used during authentication to// cause the server to call the client back at the// specified number.//// Parameters: MyReference your unique reference// DialString this is a pascal string which must// contain a dial string for the number// to call the client back at// CompletionProc this proc will be called when the callback// has been completed.// CompletionParam additional information you can provide// that will be passed to the CompletionProc//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/6/1992//// Modifications:////===========================================================================extern pascal ARAErr ARAAllowUser( SecurityReference MyReference, SecurityCompletionProc CompletionProc, long CompletionParam );//===========================================================================// Description: the authentication code on the server can call this// routine to indicate the user has passed this module's// security requirements.//// Parameters: MyReference your unique reference// CompletionProc this routine is called when AppleTalk// Remote Access has finished handling// your authentication information.//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/6/1992//// Modifications:////===========================================================================extern pascal ARAErr ARADontAllowUser( SecurityReference MyReference, char * Message, SecurityCompletionProc CompletionProc, long CompletionParam );//===========================================================================// Description: the server security module can call this routine to// prevent a user from being allowed in.//// Parameters: MyReference your unique reference// Message a pascal string stating why the user// was not allowed access// CompletionProc this routine will be called when the// request for not allowing user has bee// processed// CompletionParam additional information you can provide// which will be passed to the completion// proc//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/6/1992//// Modifications:////===========================================================================extern pascal ARAErr ARAReadSecurityData( SecurityReference MyReference, void * DataPtr, int DataSize, SecurityCompletionProc CompletionProc, long CompletionParam );//===========================================================================// Description: this routine can be used to read data for this security// module which is associated with either a user (on the// server side), or a connection (on the client side).// This routine doesn't lock the data, so use it only when// you just plan to read the data.//// Parameters: MyReference your unique reference// DataPtr where the data will be read to// DataSize maximum number of bytes to read// CompletionProc this routine will be called when the// read request has completed// CompletionParam additional information you can provide// to be passed to the completion proc//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/6/1992//// Modifications:////===========================================================================extern pascal ARAErr ARAReadLockSecurityData( SecurityReference MyReference, void * DataPtr, int DataSize, SecurityCompletionProc CompletionProc, long CompletionParam );//===========================================================================// Description: this routine can be used to read security data and lock// it to be modified. If you are planning on modifying your// data and then writing it, you must call this routine.// It locks the data until the a ARAUnlockSecurityData call.//// Parameters: MyReference your unique reference// DataPtr where the data will be read// DataSize the maximum number of bytes to read// CompletionProc this routine will be called when the// data is read into your buffer.// CompletionParam additional information you can provide to// be passed on to the CompletionProc.//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/29/1992//// Modifications:////===========================================================================extern pascal ARAErr ARAUnlockSecurityData( SecurityReference MyReference, SecurityCompletionProc CompletionProc, long CompletionParam );//===========================================================================// Description: if you have read the security data with ARAReadLockSecurityData// you must call this routine to unlock the data. After this// call others can then lock the security data.//// Parameters: MyReference your unique reference// CompletionProc this routine is called when the data is unlocked// CompletionParam additiona information you can provide to be// passed to the CompletionProc//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/29/1992//// Modifications:////===========================================================================extern pascal ARAErr ARAWriteSecurityData( SecurityReference MyReference, void * DataPtr, int DataSize, SecurityCompletionProc CompletionProc, long CompletionParam );//===========================================================================// Description: this routine can be used by the module to write private// data which is either associated with a user (on the server// side), or a connection (on the client side).//// Parameters: MyReference your unique reference// DataPtr the data to be written out// DataSize the amount of data to write out// CompletionProc this routine is called when AppleTalk// Remote Access has completed the write// operation// CompletionParam additional information you can provide// which is passed to the completion proc//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/6/1992//// Modifications:////===========================================================================extern pascal ARAErr ARAGetUserInfo( SecurityReference MyReference, void * DataPtr, int DataSize, SecurityCompletionProc CompletionProc, long CompletionParam );//===========================================================================// Description: this routine can be called to get information about the// the user, such as user name etc. It is an asynchronous// call.//// Parameters: MyReference your unique code reference// DataPtr pointer to where the user's name (Pascal// string) will be stored// DataSize maximum number of bytes to read// CompletionProc this routine will be called when the call// has completed// CompletionParam additional information to be passed to// the CompletionProc//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/6/1992//// Modifications:////===========================================================================extern pascal long ARAGetMySessionRef( SecurityReference MyReference );//===========================================================================// Description: You can call this routine to obtain the session reference// for the connection for which your code is loaded. This// value is unique and stays the same during the connection.// If you have a security module which has both a line-level// and a protocol-level authentication, you can use this// unique reference as a key to communicate between the// code resources.//// Parameters: MyReference this is your code's unique reference//// Return Value: long the session reference, NULL if there is an// error//// Creation Date: 10/29/1992//// Modifications:////===========================================================================extern pascal ARAErr ARATickleMe( SecurityReference MyReference, long TickleParam );//===========================================================================// Description: this routine can be used to have AppleTalk Remote Access// call your entry routine with a kSecurityTickleAction.// You can also provide some additional information which// is passed to the entry routine.//// Parameters: MyReference your unique reference// TickleParam additional information you can provide// which is passed to the entry proc//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/6/1992//// Modifications:////===========================================================================extern pascal ARAErr ARACompleteOperation( SecurityReference MyReference );//===========================================================================// Description: this routine can be called to terminate an operation.// It causes ARA to send a kSecurityEnd action. During// configuration for example the code resource can call// this routine to indicate that configuration has// completed.//// Parameters: MyReference your unique reference//// Return Value: ARAErr result code, nonzero indicates an error//// Creation Date: 10/6/1992//// Modifications:////===========================================================================#ifdef __cplusplus}#endif#endif // SECURITY_INTERFACEAppendix B: Security Module Shell//234567890123456789012345678901234567890123456789012345678901234567890123456789//===========================================================================// File: SecurityShell.c//// This file contains a shell for add-on security modules for Apple// Remote Access. This code can be duplicated to write an add-on// security code module.//// Copyright © 1992, 1993 Apple Computer Inc.// All rights reserved//// Author: Farzad Sarabi//// Modification history://// 5/10/1993 Farzad A little cleanup, and added a completion routine.// Some more comments// 10/6/1992 Farzad Created//===========================================================================#include "SecurityInterface.h"// #define SecurityShellVersion 0x0100//===========================================================================// Example of Your Code//===========================================================================// function prototypesstatic long DoMyStartup( SecurityReference MyReference, long LongParam );static long DoMyShutdown( SecurityReference MyReference, long LongParam );static long DoMyBegin( SecurityReference MyReference, long LongParam );static long DoMyEnd( SecurityReference MyReference, long LongParam );static long DoMyDataHandler( SecurityReference MyReference, long LongParam );static long DoMyAbortHandler( SecurityReference MyReference, long LongParam );static long DoMyTickleHandler( SecurityReference MyReference, long LongParam );pascal void MyCompletionProc( SecurityReference MyReference, int ResultCode, void * DataPtr, int DataSize, long CompletionParam );// the following is a shell for your code. It shows how your entry routine// should be structured. Empty supporting routines for the actions are// provided.// WARNING:// Don't change the name of this routine. We may change it in the// future. This is the routine ARA expects and calls.pascal long MySecurityProcEntry( SecurityActions Action, SecurityReference MyReference, long LongParam )//===========================================================================// Description: this is the entry point for the ??? security operation.// It is called by AppleTalk Remote Access to have this// security module perform the given operation. It// dispatches to a variety of routines based on the// requested action.//// Parameters: Action the action to be performed// MyReference this is a unique value representing// this instance of this code module.// DataPtr the data for this action// DataSize the size of data//// Return Value: long result code, nonzero indicates an// error. Its value is one of the// SecurityResultCodes.//// Creation Date://// Modifications:////==========================================================================={ switch ( Action ) { case kSecurityStartup: return DoMyStartup( MyReference, LongParam ); case kSecurityShutdown: return DoMyShutdown( MyReference, LongParam ); case kSecurityBegin: return DoMyBegin( MyReference, LongParam ); case kSecurityEnd: return DoMyEnd( MyReference, LongParam ); case kSecurityDataAvailable: return DoMyDataHandler( MyReference, LongParam ); case kSecurityAbort: return DoMyAbortHandler( MyReference, LongParam ); case kSecurityTickleAction: return DoMyTickleHandler( MyReference, LongParam ); } return ( kSecurityUnsupportedAction );}static long DoMyStartup( SecurityReference MyReference, long LongParam )//===========================================================================// Description: this routine handles the kSecurityStartup action. You// should allocate any memory and setup the working// environment (e.g. A5 world) here.//// Parameters: MyReference My unique reference// LongParam additional information//// Return Value: long result code, nonzero indicates error//// Creation Date://// Modifications:////==========================================================================={#pragma unused(MyReference)#pragma unused(LongParam) // this routine is called when the module has just been loaded. You // can preallocate any memory you need. You are not yet starting any // to do what this code resource is responsible for. // You can allocate and release memory in this routine. return ( kSecurityNoErr );}static long DoMyShutdown( SecurityReference MyReference, long LongParam )//===========================================================================// Description: this routine handles the kSecurityShutdown action. You// should release any memory allocated by the DoMyStartup// routine.//// Parameters: MyReference My unique reference// LongParam additional information//// Return Value: long result code, nonzero indicates error//// Creation Date://// Modifications:////==========================================================================={#pragma unused(MyReference)#pragma unused(LongParam) // this is the last routine that is called before your code resource // is released. Just do any cleanup you need to perform. ARA services // are no longer available. // You can allocate and release memory in this routine. return ( kSecurityNoErr );}static long DoMyBegin( SecurityReference MyReference, long LongParam )//===========================================================================// Description: this routine handles the kSecurityBeing action. This// routine should start the operations the code resource// must do. For example an authentication code resource// should start the authentication process.//// Parameters: MyReference My unique reference// LongParam additional information//// Return Value: long result code, nonzero indicates error//// Creation Date://// Modifications:////==========================================================================={#pragma unused(MyReference)#pragma unused(LongParam) // This routine is called to actually start the code resource to do // what it's responsible for. E.g. an authentication code resource // should start the authentication process. A configuration module // can start displaying a dialog etc. // You can allocate and release memory in this routine. return ( kSecurityNoErr );}static long DoMyEnd( SecurityReference MyReference, long LongParam )//===========================================================================// Description: this routine handles the kSecurityEnd action. The action// is sent to signal the end of the operation the code// resource was created to do.//// Parameters: MyReference My unique reference// LongParam additional information//// Return Value: long result code, nonzero indicates error//// Creation Date://// Modifications:////==========================================================================={#pragma unused(MyReference)#pragma unused(LongParam) // This routine is called when the code resource is finished. It is // called as a result of you calling ARAAllowUser, ARADontAllowUser, // ARACompleteOperation, or after ARA aborts your code resource. // You could for example cleanup any outstanding asynch calls to the // Mac OS. ARA services are no longer available. // You can allocate and release memory in this routine. return ( kSecurityNoErr );}static long DoMyDataHandler( SecurityReference MyReference, long LongParam )//===========================================================================// Description: this routine handles the kSecurityDataAvailable action.// The action is sent when data has arrived for the code// resource.//// Parameters: MyReference My unique reference// LongParam additional information//// Return Value: long result code, nonzero indicates error//// Creation Date://// Modifications:////==========================================================================={#pragma unused(MyReference)#pragma unused(LongParam) // This routine is not used in this release of the ARA Add-on Security. // In future releases we may use this to indicate data being available // for you. ARA may in the future send events to a modeless dialog // box using the DataAvailable message. // You can allocate and release memory in this routine. return ( kSecurityNoErr );}static long DoMyAbortHandler( SecurityReference MyReference, long LongParam )//===========================================================================// Description: this routine handles the kSecurityAbort action. The// abort action is sent when the code resources operation// needs to be terminated abnormally.//// Parameters: MyReference My unique reference// LongParam additional information//// Return Value: long result code, nonzero indicates error//// Creation Date://// Modifications:////==========================================================================={// you can remove the unused pragma for any of the parameters you use#pragma unused(MyReference)#pragma unused(LongParam) // This routine is called when the code resource is being aborted. // You should not make any more calls to ARA services, and you should // start your abort process. You will receive the End and Shutdown // actions a little while later. // You can allocate and release memory in this routine. return ( kSecurityNoErr );}static long DoMyTickleHandler( SecurityReference MyReference, long LongParam )//===========================================================================// Description: this routine handles the kSecurityTickle action. ARA// sends this action periodically. The action is also// generated as a result of a call to ARATickleMe routine.// //// Parameters: MyReference My unique reference// LongParam When ARA calls this value will be 0,// otherwise it is the value passed to// the ARATickleMe routine.//// Return Value: long result code, nonzero indicates error//// Creation Date://// Modifications:////==========================================================================={// you can remove the unused pragma for any of the parameters you use#pragma unused(MyReference)#pragma unused(LongParam) // ARA calls this routine periodically. You can also initiate a call // to this routine by calling ARATickleMe. When ARA calls this // routine the LongParam value will be 0 (zero). When it is called as // a result of a call to ARATickleMe the LongParam will have the value // you passed to ARATickleMe. // You can allocate and release memory in this routine. return ( kSecurityNoErr );}pascal void MyCompletionProc( SecurityReference MyReference, int ResultCode, void * DataPtr, int DataSize, long CompletionParam )//===========================================================================// Description: this is an example of your a completion routine you can// use for calls to asynch ARA services. You can use one// completion proc and distinguish the reason it was called// by the value passed in the CompletionParam.// //// Parameters: MyReference your unique reference// ResultCode result of the asynch ARA call you made// DataPtr pointer to the data passed to the ARA// proc// DataSize actual size of the data// CompletionParam additional information you provided // to the ARA service proc//// Return Value: none//// Creation Date://// Modifications:////==========================================================================={// you can remove the unused pragma for any of the parameters you use#pragma unused(MyReference)#pragma unused(ResultCode)#pragma unused(DataPtr)#pragma unused(DataSize)#pragma unused(CompletionParam) // WARNING: // Do not attempt to allocate or release any memory in this // routine. Also don't call any Mac Toolbaox/OS routines // that allocate or release memory. If you need to do this, // you should call ARATickleMe with a state indicator, and // allow your DoMyTickle routine to handle it. return;}Appendix C: MiscellaneousRuntime EnvironmentARA builds an A5 world for a code resource, so the module can have its own global data. ARA sets the A5 world automatically, prior to calling any routines (entry, completion) in the code resource.The module inherits stacks from other executing tasks, and should refrain from recursion and large stack variables.The resource file from which the code resources are loaded will be on the top of the resource file stack, when ARA executes code resources. The security module's resource file is opened as read-only, and you should not attempt to modify or add any resources.You must initialize any Toolbox manager's you are using (e.g. InitGraf).Building an Add-on Security ModuleYou need MPW 3.2 or later and MPW C to build a security module. The ARA Security Interface disk contains the files you need to build a security interface.The EmptyShell is a good starting point for putting together a code resource. You can also use the sample module as the starting point for your module. This code can be used in your security modules, but you must keep Apple's copyrights in the source files.After you have designed your security module (e.g. line-level vs. protocol-level and its working behavior), take the "SecurityShell.c" and code the routines that handle the actions. The Sample Module shows how a protocol-level module that provides a second password is coded.You must also define the proper 'sinf' resource for your module.After you have compiled the module you must link it with "SecurityInterface.o". You must also link in "Runtime.o" (included with MPW). SecurityInterface.o must be the first file in the link command. The link command should also have "-m SECURITYINTERFACEENTRYPROC".For an example of how a security module is build Review the enclosed Sample Module.ARA Security Interface DiskThe enclosed developer disk contains the interface files and sample modules you can use to build an ARA security module. This sections describes the contents of this disk.The "Empty Shell" folder contains a file you can use to build a code resource file. It contains place holder routines for processing the ARA actions.The "Sample Protocol Module" folder contains the complete source for a security module that provides a second password. Using this module, you can assign each user a second password. This is a protocol-level module. You can use this code as a starting point for building your own module."Security Interfaces" folder contains the various header files for interfacing with ARA. "SecurityInterface.h", and "SecurityPublic.h" contain all the declarations that your module needs for accessing ARA Service Routines. "SecurityResInfo.h" contains the flags that are used in the 'sinf' resource. "SecurityTypes.r" has the resource declarations for a security module."SecurityLibraries" contains "SecurityInterface.o" that must be linked as the first file for each of your code resources.º d ˇ ˇˇˇˇ d